Re-introduce IWC tools in agent-operations layer#22626
Draft
dannon wants to merge 14 commits intogalaxyproject:devfrom
Draft
Re-introduce IWC tools in agent-operations layer#22626dannon wants to merge 14 commits intogalaxyproject:devfrom
dannon wants to merge 14 commits intogalaxyproject:devfrom
Conversation
Centralises manifest fetching, enrichment, and token-overlap search in its own module under lib/galaxy/agents/. Module-level cache (vs. per- request) is the fix for the issue that prompted the previous IWC removal: AgentOperationsManager is instantiated per request, so a cache on it never hit.
Returns the full IWC manifest as enriched workflow entries. Reuses the module-level cache in galaxy.agents.iwc so repeated calls within an hour hit memory.
Wraps the token-overlap search in galaxy.agents.iwc.search_workflows so agents can find IWC entries by keyword.
Imports an IWC manifest entry as a StoredWorkflow via the in-process workflow_contents_manager.build_workflow_from_raw_description path -- the same one the workflows REST API uses. Replaces the previous attempt that called WorkflowsManager.import_workflow_dict (a method that exists on BioBlend's GalaxyInstance.workflows, not on the internal manager). Adds an integration smoke test that exercises the full path with the manifest fetch mocked.
Both were near-duplicates of search_iwc_workflows for an LLM agent. get_iwc_workflows dumps the entire enriched manifest (~150 entries, huge context cost). recommend_iwc_workflows shared the same token- overlap implementation as search, just with a different docstring framing. Collapse to a single search_iwc_workflows(query, limit=10) that handles both keyword queries and natural-language intent. External clients can still browse the full manifest via the IWC website; the agent layer is intent-driven.
mvdbeek
reviewed
May 2, 2026
Member
if we don't want that, the pattern would be to register a singleton with lagom on the app container |
The tool_recommendation agent now also surfaces IWC workflows when the ask is analysis-shaped rather than tool-shaped: "which tool sorts a BAM?" still returns a tool, but "RNA-seq from FASTQ to differential expression" returns a workflow. Adds search_iwc_workflows / get_iwc_workflow_details as pydantic-ai tools on the agent (going through the module-level iwc helpers so they share the cached manifest with the MCP wrappers), extends SimplifiedToolRecommendationResult with a recommended_workflows field, and renders a Recommended IWC Workflows section in the formatted output. Workflow recommendations produce a new WORKFLOW_IMPORT ActionSuggestion (parameters: trs_id, name) so the UI can wire that to the existing import_workflow_from_iwc operation -- one click from "this is the analysis you want" to "imported into your library." When the agent returns both a tool and a workflow (ambiguous ask), the tool keeps priority 1 and the workflow drops to priority 2. Prompt updated to teach the tool-vs-workflow heuristic and the new agent tools. Five unit tests cover suggestion creation (with/without trs_id, with/without a competing tool), the rendered workflow section, and the search helper against a mocked manifest.
Per Marius' review: we already depend on cachetools, so swap the hand-rolled module-globals + threading.Lock cache for the standard @cached(cache=TTLCache(maxsize=1, ttl=...)) pattern. clear_manifest_cache() now just calls TTLCache.clear() under the same lock cachetools uses for read/write. Pre-warming via celery beat remains as possible follow-up.
The CI mypy job fails on pre-existing tests where the SAMPLE_MANIFEST dict literal narrows steps to Collection[str] (so step["0"] becomes "not indexable"), and where AgentOperationsManager is constructed with SimpleNamespace stand-ins for app/trans. Annotate the manifest fixture as list[dict[str, Any]] and cast() the SimpleNamespace args so the type-only assertions still pass without changing behavior.
ActionType gained a workflow_import variant for the IWC workflow recommendation suggestion; refresh client/src/api/schema/schema.ts so the OpenAPI validation CI job stays green.
Per Codex review: cachetools.cached(lock=...) only protects cache reads/writes, so concurrent cold misses in one worker can each issue their own iwc.galaxyproject.org request. Drop the decorator and fetch under the lock so a single concurrent caller does the network and the others wait for the result. Still backed by TTLCache for the hour-long TTL behavior Marius asked for.
Codex flagged that ActionType.WORKFLOW_IMPORT was emitted by the recommender but the chat UI's switch had no case for it -- clicking the quick action fell through to support. Add a thin REST endpoint that wraps AgentOperationsManager.import_workflow_from_iwc, hook the agentActions handler to POST to it, give ActionCard.vue a faFileImport icon, and regenerate client/src/api/schema/schema.ts. On success the user lands in the workflow editor; missing tools surface as a warning toast so they know the workflow imported but can't run yet.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds IWC (Intergalactic Workflows Commission) workflow recommendations to the agent-operations / MCP layer, plus a one-click import path through the chat UI. This is a re-introduction -- the previous attempt was reverted in
71d3d0922f6for two specific reasons that are addressed here.What's fixed from the previous attempt
Process-wide cache that actually hits. The previous version kept the manifest cache on
AgentOperationsManager, which is instantiated per request -- so the cache never hit. The cache now lives at module scope inlib/galaxy/agents/iwc.pyas acachetools.TTLCache(maxsize=1, ttl=3600)with athreading.Lockheld across the network fetch (single-flight, so concurrent cold misses share one in-flight request rather than fanning out).Correct workflow-import path. The previous version called
WorkflowsManager.import_workflow_dict, a method that exists on BioBlend'sGalaxyInstance.workflowsbut not on the internal manager. The new path usesapp.workflow_contents_manager.ensure_raw_description(...)followed bybuild_workflow_from_raw_description(...)-- the same path the workflows REST API uses. Imports useWorkflowCreateOptions(publish=False, importable=False, import_tools=False), so they end up as private StoredWorkflows owned by the calling user.MCP tools (3, intentionally)
search_iwc_workflows(query, limit=10)-- token-overlap rank against name, description, tags, readme, and constituent tool names. Handles both keyword queries ("rnaseq") and natural-language intent ("variant calling from whole exome sequencing").get_iwc_workflow_details(trs_id)-- single workflow, full readme included.import_workflow_from_iwc(trs_id)-- materializes the manifest entry as a private StoredWorkflow. Returnsmissing_tools(tool ids referenced by the workflow that aren't installed locally) so the agent can flag a workflow that imported but won't run until an admin installs them.The galaxy-mcp server has separate
get_iwc_workflowsandrecommend_iwc_workflowstools; both are redundant for an LLM agent (the former dumps the whole 150+-entry manifest into context, the latter is the same token-overlap assearchwith a different docstring). Collapsed to one search tool with alimitarg.Recommender (Tool Recommendation agent)
The existing
tool_recommendationagent now surfaces IWC workflows alongside tools. The heuristic in the prompt: tool for atomic asks ("which tool sorts a BAM?"), workflow for analysis-shaped asks ("RNA-seq from FASTQ to differential expression"), both when ambiguous.search_iwc_workflowsandget_iwc_workflow_detailsare wired up as pydantic-ai tools on the agent andSimplifiedToolRecommendationResultgains arecommended_workflowsfield that renders alongside the tools section.One-click import from chat
ActionType.WORKFLOW_IMPORT(parameters:trs_id,name) emitted from the recommender when a workflow is recommended.POST /api/workflows/from_iwcREST endpoint that wrapsAgentOperationsManager.import_workflow_from_iwc.client/src/composables/agentActions.tsPOSTs to that endpoint, navigates to the workflow editor on success, and surfacesmissing_toolsas a warning toast.Subworkflow definition mutation
build_workflow_from_raw_descriptionmutates subworkflow step dicts in place. Because the IWC manifest is process-cached, passing the cached definition straight in would corrupt the cache for subsequent users in the same worker. The import path nowdeepcopys the definition before handing it to the builder, with a regression test intest/unit/agents/test_operations_iwc.pythat uses a deliberately-mutating mock to confirm the cached dict survives.Tests
test/unit/agents/test_iwc.py-- 8 unit tests for the helper module (cache, enrichment, ranking, edge cases). HTTP mocked.test/unit/agents/test_operations_iwc.py-- regression test for the deep-copy fix.test/unit/app/test_agents.py-- 5 unit tests for the recommender's workflow surface (suggestion creation, missing-trs_id skip, render, search helper against mocked manifest).test/integration/test_agents.py::TestMCPServerSmoke::test_mcp_import_workflow_from_iwc-- end-to-end through the MCP server with the manifest fetch mocked.Out of scope
Test plan
search_iwc_workflows("rnaseq")->get_iwc_workflow_detailson a result ->import_workflow_from_iwc-- confirm the workflow lands as a private StoredWorkflow andmissing_toolsmakes sense./api/workflows/from_iwcand lands you in the workflow editor.